package expressions;

import values.Integer;
import values.Value;
import base.AST;
import base.Environment;
import base.Interpreter;

public class Modulo implements Expression {

	private AST son1;
	private AST son2;

	/**
	 * Creates an expression that represents eval(son1) % eval(son2)
	 * 
	 * @param son1
	 *            a Value or an Expression
	 * @param son2
	 *            a Value or an Expression
	 */

	public Modulo(AST son1, AST son2) {
		assert son1 instanceof Value || son1 instanceof Expression;
		assert son2 instanceof Value || son2 instanceof Expression;
		this.son1 = son1;
		this.son2 = son2;
	}

	/**
	 * Returns eval(son1) % eval(son2) if eval(son1) and eval(son2) are integers
	 * and eval(son2) > 0. Returns false otherwise
	 * 
	 * @throws BadExpressionException
	 */

	public Value eval(Environment env) throws BadExpressionException {

		Integer a = Interpreter.getInt(this.son1, env);
		Integer b = Interpreter.getInt(this.son2, env);

		if (a != null && b != null)
			if (b.eval() < 0)
				throw new BadExpressionException(
						"Trying to modulo a % b with b <= 0");
			else
				return new Integer(a.eval() % b.eval());
		else
			throw new BadExpressionException(
					"Applying modulo on non-integer values");
	}

}
